use axum::{
    http::{StatusCode},

    Json, extract::Path,
};
use serde::{Serialize};
use std::{
    path::{PathBuf},
};
use tokio::fs as async_fs;
use anyhow::{Result, anyhow};
use std::time::SystemTime;

// 目录信息结构
#[derive(Serialize, Debug)]
pub struct DirectoryInfo {
    name: String,
    path: String,
    modified: u64, // 时间戳（秒）
}

// 目录内容响应
#[derive(Serialize, Debug)]
pub struct DirectoryContent {
    path: String,
    directories: Vec<DirectoryInfo>,
}

// jsTree 节点结构
#[derive(Serialize, Debug)]
pub struct JsTreeNode {
    id: String,
    text: String,
    state: NodeState,
    children: bool,
    icon: &'static str,
}

#[derive(Serialize, Debug)]
pub struct NodeState {
    opened: bool,
    disabled: bool,
    selected: bool,
}


// 获取目录树（用于 jsTree）

pub async fn list_directories(
    path: Option<Path<String>>,
) -> Result<Json<Vec<JsTreeNode>>, StatusCode> {
    let requested_path = match path {
        Some(p) => p,
        None => axum::extract::Path("".to_string()),
    };
    let root_dir = crate::util::get_system_root();
    let dir_path = get_safe_path(&root_dir, &requested_path)
        .map_err(|_| StatusCode::BAD_REQUEST)?;

    let entries = match async_fs::read_dir(&dir_path).await {
        Ok(entries) => entries,
        Err(_) => return Err(StatusCode::INTERNAL_SERVER_ERROR),
    };

    let mut nodes = Vec::new();
    let mut has_subdirectories = false;

    // 先检查是否有子目录
    tokio::pin!(entries); // 固定异步迭代器
    while let Ok(Some(entry)) = entries.next_entry().await {
        let metadata = entry.metadata().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
        
        if metadata.is_dir() {
            has_subdirectories = true;
            break;
        }
    }

    // 如果是根目录且没有子目录，返回错误
    if requested_path.is_empty() && !has_subdirectories {
        return Err(StatusCode::NOT_FOUND);
    }

    // 重新读取目录获取所有子目录
    let entries = async_fs::read_dir(&dir_path).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    
    tokio::pin!(entries); // 再次固定异步迭代器
    while let Ok(Some(entry)) = entries.next_entry().await {
        let metadata = entry.metadata().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
        
        if metadata.is_dir() {
            let name = entry.file_name().into_string().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
            let path = format!("{}/{}", requested_path.as_str(), name).trim_start_matches('/').to_string();
            
            nodes.push(JsTreeNode {
                id: path.clone(),
                text: name,
                state: NodeState {
                    opened: false,
                    disabled: false,
                    selected: false,
                },
                children: has_subdirectory(&root_dir.join(&path)).await,
                icon: "fa fa-folder",
            });
        }
    }
    Ok(Json(nodes))
}

// 获取子目录列表

pub async fn list_subdirectories(
    Path(path): Path<String>,
) -> Result<Json<DirectoryContent>, StatusCode> {
    let root_dir = crate::util::get_system_root();
    let dir_path = get_safe_path(&root_dir, &path)
        .map_err(|_| StatusCode::BAD_REQUEST)?;

    let entries = match async_fs::read_dir(&dir_path).await {
        Ok(entries) => entries,
        Err(_) => return Err(StatusCode::INTERNAL_SERVER_ERROR),
    };

    let mut directories = Vec::new();

    tokio::pin!(entries);
    while let Ok(Some(entry)) = entries.next_entry().await {
        let metadata = entry.metadata().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
        
        if metadata.is_dir() {
            let name = entry.file_name().into_string().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
            let dir_path = format!("{}/{}", path, name).trim_start_matches('/').to_string();
            
            let modified = metadata.modified()
                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
                .duration_since(SystemTime::UNIX_EPOCH)
                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
                .as_secs();
            
            directories.push(DirectoryInfo {
                name,
                path: dir_path,
                modified,
            });
        }
    }

    // 按名称排序
    directories.sort_by_key(|d| d.name.to_lowercase());

    Ok(Json(DirectoryContent {
        path,
        directories,
    }))
}

// 检查路径是否有子目录
async fn has_subdirectory(path: &std::path::Path) -> bool {
    match async_fs::read_dir(path).await {
        Ok(mut entries) => {
            while let Some(entry) = entries.next_entry().await.ok().flatten() {
                if let Ok(metadata) = entry.metadata().await {
                    if metadata.is_dir() {
                        return true;
                    }
                }
            }
            false
        }
        Err(_) => false,
    }
}

// 安全路径处理
fn get_safe_path(root: &std::path::Path, requested: &str) -> Result<PathBuf> {
    let mut safe_path = root.to_path_buf();
    
    // 处理相对路径
    if !requested.is_empty() {
        for component in requested.split('/') {
            // 防止路径遍历攻击
            if component == ".." || component.starts_with('.') {
                return Err(anyhow!("无效的路径组件"));
            }
            safe_path.push(component);
        }
    }
    
    // 验证路径是否在根目录内
    if !safe_path.starts_with(root) {
        return Err(anyhow!("禁止访问此路径"));
    }
    
    Ok(safe_path)
}

